package gfo

/*Tournament
* --------------------------------------
* Tournament embodies the Smash tournaments themselves. Each tournament, in addition to having a name and
* date (typically tournaments are named 'George Foreman Open ___', where ___ is a roman number that is
* roughly equivalent to a sequential ID [my freshman year I started with the GFO XIII, now we're on the XXII]).
* The Tournament:show view is unique and the functionality of the mehtods in Tournament reflect that.*/
class Tournament {
    String name
    String description
    int id
    Date date
    static hasMany = [matches: Match]

    static constraints = {
        matches(nullable: true)
        description(nullable: true)
    }

    String toString(){
        "$name"
    }

    /*toAbbrv
    * --------------------------------------------------
    * This function replaces 'George Foreman Open' with 'GFO' in the tournament's name attribute for
    * the sake of brevity.*/
    String toAbbrv(){
        def abbrv = this.name
        return abbrv.replace("George Foreman Open", "GFO")
    }

    /*findMatchByPlayers
    * -------------------------------
    * This function is used for Tournament:show.gsp for the Round-Robin grid I've implemented.
    * It is a GORM function at heart, but due to the fact that Player is not an attribute of Match,
    * Matchship becomes involved in the search process, complicating matters.*/
    Match findMatchByPlayers(Player player1, Player player2){//originally had bracket as an argument, don't think we need it
        def matches = Match.findAllByTournamentAndBracket(this,Bracket.findByName("Round Robin"))
        for (match in matches){
            def ms1 = Matchship.findByPlayerAndMatch(player1, match)//the player's entire matchship history
            def ms2 = Matchship.findByPlayerAndMatch(player2, match)//""
            if (ms1!=null && ms2!=null){
                return match
            }
        }
        return null
    }

    /*hasBracketMatches
    * ---------------------------------
    * 'Bracket' is an attribute used to refer to a particular stage of progression in the
    * tournament, however when one says 'Bracket matches' they essentially mean matches that
    * aren't in the initial Round Robin pool. Most tournaments have a finals series, but a few
    * don't and for that reason we need to know not to show anything for non-existent Bracket
    * matches.*/
    Boolean hasBracketMatches(){//can't compare bracket objects with this, not sure why
        for (match in this.matches){
            if (match.bracket.id != Bracket.findByName("Round Robin").id){
                print match.bracket.id
                print Bracket.findByName("Round Robin").id
                print match
                return true
            }
        }
        return false
    }

    /*findBracketMatchups
    * -----------------------------------------------
    * This is more or less strictly used for the show view. The idea is to determine, for each Bracket
    * after the Round Robin, the pairings of players for each round. It should return something along
    * the lines of a List of Tuples, however I realized that its implementation was too hard to spend
    * as much time as I needed to on it, so it sort of took a backseat and hasn't been finished.*/
    Set<Player> findBracketMatchups(Bracket bracket){//spending too much time on this; might work, might not.
        def matchups = []
        for (match in Match.findByTournamentAndBracket(this, bracket)){
            def msList = match.players.toList()
            if (!msList in matchups){
                matchups.add(msList)
            }
        }
    }

    /*gitWinner
    * -----------------------------------
    * gitWinner remains to be used. This method can't be called 'getWinner' because Grails is too smart
    * for its own good and complains about not being able to find a 'winner' attribute of a tournament instance
    * and also about the fact that there's no setter. As it is, gitWinner should look through all of the Finals
    * matches, determine who won the most and return that player.*/
    Player gitWinner(){
        def playerRecords = [:]//no clue if this works or not; it's unwieldy as hell
        for (match in Match.findAllByTournamentAndBracket(this,Bracket.findByName("Finals"))){
            for (ms in match.players){
                if (ms.winner){
                    if (!playerRecords[ms.player]){
                        playerRecords[ms.player] = 1
                    }
                    else{
                        playerRecords[ms.player] ++
                    }
                }
            }
        }
        for (player in playerRecords.keySet()) {
            if (playerRecords[player] == 3) {
                return player as Player
            }
        }
    }

    /*roster
    * ---------------------------
    * roster returns a list of players who participated in a particular tournament.*/
    List<Player> roster(){
        def players = []
        for (match in this.matches){
            for (ms in match.players){
                if (!(ms.player in players)){
                    players.add(ms.player)
                }
            }
        }
        return players
    }

    /*rrRecord
    * --------------------------
    * Takes a player and determines their overall record in the Round Robin, returning a string that
    * is formatted in the traditional way (wins - losses).*/
    String rrRecord(Player player){//LEFT OFF AROUND HERE (JUST GOT THIS WORKING), SEE SHOW VIEW
        def total = this.roster().size()-1
        def wins = 0
        for (match in this.matches){
            for (ms in match.players){
                if (ms.player.id == player.id && ms.winner){
                    wins ++
                }
            }
        }
        return "$wins - ${total-wins}"
    }

    String rrResult(Player rowPlayer, Player colPlayer){
        //print(rowPlayer)
        //print(colPlayer)
        def match = this.findMatchByPlayers(rowPlayer, colPlayer)
        //print(match?.toString())
        //print(", ")
        def winner = match?.determineWinner()
        if (!winner){
            return "NA"
        }
        else if (winner.id == rowPlayer.id){
            return "1 - 0"
        }
        else{
            return "0 - 1"
        }

    }
}
